package com.example.mybatislearn.common.mapper.converter;

import com.example.mybatislearn.common.lang.Pair;
import com.example.mybatislearn.common.mapper.exception.SmartMapperException;
import com.example.mybatislearn.common.mapper.converter.customer.SmartTypeConverter;
import org.dozer.ConfigurableCustomConverter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SmartFieldCustomConverter implements ConfigurableCustomConverter {
    private static Map<Pair<Class, Class>, Map<Pair<String, String>, SmartTypeConverter>> fieldTypeConverterMap = new ConcurrentHashMap<>();

    private Class baseSrcType;

    private Class baseDestType;

    private String srcFieldName;

    private String destFieldName;

    private SmartTypeConverter typeConverter;

    public SmartFieldCustomConverter() {

    }

    public static void addFieldTypeConverter(Class srcType, Class destType, String srcFieldName, String destFieldName, SmartTypeConverter typeConverter) {
        Pair<Class, Class> srcDestClassKey = new Pair<>(srcType, destType);

        Map<Pair<String, String>, SmartTypeConverter> fieldMap = fieldTypeConverterMap.get(srcDestClassKey);
        if (fieldMap == null) {
            fieldMap = new ConcurrentHashMap<>();
            fieldTypeConverterMap.put(srcDestClassKey, fieldMap);
        }
        fieldMap.put(new Pair<>(srcFieldName, destFieldName), typeConverter);
    }

    @Override
    public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class<?> destinationClass, Class<?> sourceClass) {
        if (typeConverter == null) {
            initTypeConverter();
        }

        if (typeConverter != null) {
            return typeConverter.convert(existingDestinationFieldValue, sourceFieldValue, destinationClass, sourceClass);
        }

        return existingDestinationFieldValue;
    }

    private void initTypeConverter() {
        Map<Pair<String, String>, SmartTypeConverter> fieldMap = fieldTypeConverterMap.get(new Pair<>(baseSrcType, baseDestType));
        if (fieldMap != null) {
            typeConverter = fieldMap.get(new Pair<>(srcFieldName, destFieldName));
        }
    }

    @Override
    public void setParameter(String parameter) {
        // srcClassName,destClassName|srcFieldName,destFieldName
        try {
            String[] classFieldArray = parameter.split("\\|");
            String[] classArray = classFieldArray[0].split(",");
            String[] fieldArray = classFieldArray[1].split(",");

            baseSrcType = Class.forName(classArray[0]);
            baseDestType = Class.forName(classArray[1]);
            srcFieldName = fieldArray[0];
            destFieldName = fieldArray[1];

            initTypeConverter();
        } catch (Exception e) {
            throw new SmartMapperException(e.getMessage(), e);
        }
    }
}
